package com.example.config;

import com.alibaba.fastjson.JSON;
import com.example.annotation.WebApiResponseBody;
import com.example.model.WebApiResponse;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 自定义RequestResponseBodyMethodProcessor
 */
public class WebApiRequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {

    public WebApiRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters) {
        super(converters);
    }

    public WebApiRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters, @Nullable ContentNegotiationManager contentNegotiationManager) {
        super(converters, contentNegotiationManager);
    }

    public WebApiRequestResponseBodyMethodProcessor(List<HttpMessageConverter<?>> converters, @Nullable ContentNegotiationManager manager, @Nullable List<Object> requestResponseBodyAdvice) {
        super(converters, manager, requestResponseBodyAdvice);
    }

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return false;
    }

    @Nullable
    @Override
    public Object resolveArgument(MethodParameter methodParameter, @Nullable ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, @Nullable WebDataBinderFactory webDataBinderFactory) throws Exception {
        return null;
    }

    @Override
    public boolean supportsReturnType(MethodParameter methodParameter) {
        return methodParameter.hasMethodAnnotation(WebApiResponseBody.class) ||
                methodParameter.hasMethodAnnotation(ResponseBody.class);
    }

    @Override
    public void handleReturnValue(@Nullable Object o, MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest) throws Exception {
        HttpServletResponse response = nativeWebRequest.getNativeResponse(HttpServletResponse.class);
        if (methodParameter.hasMethodAnnotation(WebApiResponseBody.class)) {
            WebApiResponse webApiResponse = new WebApiResponse();
            webApiResponse.setData(o);
            webApiResponse.setCode(WebApiResponse.SUCCESS_CODE);
            modelAndViewContainer.setRequestHandled(true);
            response.setContentType("text/plain;charset=UTF-8");
            response.getWriter().append(JSON.toJSONString(webApiResponse)).flush();
        } else {
            modelAndViewContainer.setRequestHandled(true);
            response.setContentType("text/plain;charset=UTF-8");
            if (o instanceof String) {
                response.getWriter().write(o.toString());
            } else {
                response.getWriter().append(JSON.toJSONString(o)).flush();
            }
        }
    }
}
